package control.manager
{
	import data.BitmapItem;
	import data.GameConst;
	import data.RoleVO;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.system.ApplicationDomain;
	import flash.utils.Dictionary;
	import flash.utils.getDefinitionByName;
	
	import ghostcat.display.movieclip.GMovieClip;
	
	import view.item.MapTileItem;
	import view.layer.RoleLayer;
	import view.role.MapMonster;
	import view.role.MapNPC;
	import view.role.MapObject;

	/**
	 * 位图管理类 
	 * @author leo
	 * 
	 */	
	public class BitmapManager
	{
		private static var _instance :BitmapManager = null;
		/**
		 *  角色切块行数，与列数是一样,8*8
		 */		
		private const ROLETILECOLS :int = 8;

		/**
		 * 缓存的地图块列表 
		 */		
		public var mapTileItemList :Vector.<MapTileItem>;
		/**
		 * 角色图片缓存，因为要重复利用，不能销毁，只读取 
		 */		
		public var roleBitmapDict :Dictionary;
		/**
		 * npc 的bitmapdata列表，已经切割好，重复利用 
		 */		
		public var npcBMDList :Array;
		/**
		 * 怪物的bitmapdata列表 ，已经切割好，重复利用 
		 */		
		public var monsterBMDList :Array;
		/**
		 * 技能动画字典 
		 */		
		public var skillDict :Dictionary;
		/**
		 * 是否已经有切割好的npc位图列表
		 */		
		private var npcIsHaveBMD :Boolean;
		/**
		 * 是否已经有切割好的怪物位图列表 
		 */		
		private var monsterIsHaveBMD :Boolean;
		/**
		 * 人物资源还没加载完时显示的默认图片  
		 */		
		private var _defRoleBMD :BitmapData;
		
		public function BitmapManager(prvClass :PrivateClass)
		{
			this.mapTileItemList = new Vector.<MapTileItem>();
			this.roleBitmapDict = new Dictionary();
			this.npcBMDList = [];
			this.monsterBMDList = [];
			this.skillDict = new Dictionary();
		}
		/**
		 * 获取角色的位图列表来播放 
		 * @param roleData
		 * @return 
		 * 
		 */		
		public function getRoleBMDList(roleData :*):Array
		{
			var result :Array;
			switch(roleData.roleType)
			{
				case RoleVO.NPC :
					if(this.npcIsHaveBMD)
					{
						result = this.npcBMDList;
					}else
					{
						this.cutRoleBitmapData(roleData);
						result = this.npcBMDList;
						this.npcIsHaveBMD = true;
					}
					break;
				case RoleVO.MONSTER:
					if(this.monsterIsHaveBMD)
					{
						result = this.monsterBMDList;
					}else
					{
						this.cutRoleBitmapData(roleData);
						result = this.monsterBMDList;
						this.monsterIsHaveBMD = true;
					}
					break;
			}
			return result;
		}
		/**
		 * 获取技能 
		 * @param name
		 * @return 
		 * 
		 */		
		public function getSkill(name :String):MovieClip
		{
			if(this.skillDict[name])
			{
				return this.skillDict[name] as MovieClip;
			}else
			{
				this.skillDict[name] = getMCByName(name);
				return getSkill(name);
			}
			return null;
		}
		
		public function getMCByName(name :String):MovieClip
		{
			if(ApplicationDomain.currentDomain.hasDefinition(name))
			{
				var cls :Class = ApplicationDomain.currentDomain.getDefinition(name) as Class;
				var mc :MovieClip = new cls() as MovieClip;
				return mc;
			}
			return null;
		}
		/**
		 * 清理地图缓存，包括怪物和npc
		 * 
		 */		
		public function clearMapCache():void
		{
			//清理地图块
			if(this.mapTileItemList.length > 0)
			{
				var len :int = this.mapTileItemList.length - 1;
				for(var index :int = len; index >= 0; index--)
				{
					var mapTileItem :MapTileItem = this.mapTileItemList[index] as MapTileItem;
					if(mapTileItem.parent)
					{
						mapTileItem.parent.removeChild(mapTileItem);
					}
					if(mapTileItem.bitmapData)
					{
						mapTileItem.bitmapData.dispose();
					}
					mapTileItem = null;
					this.mapTileItemList.splice(index,1);
				}
			}
			
			//删除当前地图的npc和怪物
			var roleLayer :RoleLayer = LayerManager.instance.getLayer(RoleLayer.NAME) as RoleLayer;
			var roleList :Array = RoleManager.instance.roleList;
			if(roleList.length > 0)
			{
				for(var i :int = roleList.length - 1; i>=0; i--)
				{
					var item :MapObject = roleList[i] as MapObject;
					if(!item) return;
					if(item.roleData.roleType == RoleVO.NPC || item.roleData.roleType == RoleVO.MONSTER)
					{
						roleLayer.removeChild(item);
						item = null;
						roleList.splice(i,1);
					}
				}
			}
			
		}
		/**
		 * 根据地图块uid查找是否已经加载过 
		 * @param uid
		 * @return 
		 * 
		 */		
		public function findMapTileItem(uid :String) :MapTileItem
		{
			var item :MapTileItem;
			for each(var mapTileItem :MapTileItem in mapTileItemList)
			{                                               
				if(mapTileItem.uid == uid)
				{
					item = mapTileItem;
				}
			}
			return item;
		}
		
		/**
		 * 位图切割成小位图数组
		 * @param source bmd源
		 * @param tileW 切块宽
		 * @param tileH 切块高
		 * @param row 第几行
		 * @return 
		 * 
		 */
		public function cutBitmapData(source :BitmapData,tileW :int,tileH :int,row :int):Vector.<BitmapData>
		{
			var result :Vector.<BitmapData> = new Vector.<BitmapData>();
			
			for(var i :int = 0; i < ROLETILECOLS; i++)
			{
				var bitmapData :BitmapData = new BitmapData(tileW,tileH,true,0);
				bitmapData.lock();
				bitmapData.copyPixels(source,new Rectangle(i * tileW, row * tileH,tileW,tileH),new Point());
				bitmapData.unlock();
				result.push(bitmapData);
			}
			
			return result;
		}
		
		
		/**
		 * 左右旋转bitmapData 
		 * @param sourceList
		 * @return 
		 * 
		 */		
		public function rotationBitmapData(sourceList :Vector.<BitmapData>):Vector.<BitmapData>
		{
			if(!sourceList || sourceList.length == 0)
			{
				trace("sourceList null");
				return null;
			}
			var result :Vector.<BitmapData> = new Vector.<BitmapData>();
			for each(var elem :BitmapData in sourceList)
			{
				var newBMD :BitmapData = new BitmapData(elem.width,elem.height,true,0);
				for(var row :int = 0; row < elem.width; row++)
				{
					for(var col :int = 0; col < elem.height; col++)
					{
						newBMD.lock();
						newBMD.setPixel32(elem.width - row,col,elem.getPixel32(row,col));
						newBMD.unlock();
					}
				}
				result.push(newBMD);
			}
			
			return result;
		}
		
		/**
		 * 人物资源还没加载完时显示的默认图片 
		 */
		public function get defRoleBMD():BitmapData
		{
			if(!_defRoleBMD)
			{
				if(ApplicationDomain.currentDomain.hasDefinition("DefautAsset"))
				{
					var cls :Class = getDefinitionByName("DefautAsset") as Class;
					_defRoleBMD = new cls() as BitmapData;
				}
			}
			return _defRoleBMD;
		}
		

		public static function get instance():BitmapManager
		{
			if(_instance == null)
			{
				_instance = new BitmapManager(new PrivateClass());
			}
			return _instance;
		}
		/**
		 * 位图切割 
		 * @param roleData
		 * 
		 */		
		private function cutRoleBitmapData(roleData :*):void
		{
			//现有的方向图片信息
			var frameNameAry :Array;
			var url :String;
			var actionName :String;
			var result :Vector.<BitmapData>;
			var bmd :BitmapData;
			var tileW :int;
			var tileH :int;
			
			
			var len :int = roleData.action.length;
			for(var index :int = 0; index < len; index++)
			{
				var actionIndex :int = 0;
				url = roleData.roleURL  + roleData.roleType + "_" + roleData.action[index] + ".png";
				if(this.roleBitmapDict[url])
				{
					//缓存
					bmd= roleBitmapDict[url] as BitmapData;
				}else
				{
					trace("没有角色缓存图片");
				}
				actionName = getActionName(url,roleData);
				switch(actionName)
				{
					case "walk":
						frameNameAry = RoleVO.walkNameAry;
						break;
					case "wait":
						frameNameAry = RoleVO.waitNameAry;
						break;
				}
				tileW = bmd.width/ROLETILECOLS;
				tileH = bmd.height/ROLETILECOLS;
				for(var i :int = 0; i < ROLETILECOLS; i++)
				{
					result = BitmapManager.instance.cutBitmapData(bmd,tileW,tileH,i);
					var name :String = frameNameAry[i] as String;
					if(roleData.roleType == RoleVO.NPC)
					{
						this.npcBMDList[name] = result;
						
					}else if(roleData.roleType == RoleVO.MONSTER)
					{
						this.monsterBMDList[name] = result;
					}
				}
			}
		}
		
		/**
		 * 获取动作名字，walk or wait or... 
		 * @param str
		 * @return 
		 * 
		 */		
		private function getActionName(str :String,roleData :*):String
		{
			var result :String;
			var len :int = roleData.action.length;
			
			for(var index :int = 0; index < len; index++)
			{
				if(str.indexOf(roleData.action[index]) != -1)
				{
					result = roleData.action[index];
				}
			}
			return result;
		}


	}
}
class PrivateClass{}